using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Entities;
using Volo.Abp;

namespace Acme.BookStore.Workzmy
{
    public class AllocationAppService :
        CrudAppService<
            Allocation,
            AllocationDto,
            Guid,
            GetAllocationListDto,
            CreateUpdateAllocationDto,
            CreateUpdateAllocationDto>,
        IAllocationAppService
    {
        private readonly IRepository<Allocation, Guid> _allocationRepository;
        private readonly IRepository<AllocationDetail, Guid> _allocationDetailRepository;
        private readonly IRepository<FileUpload, Guid> _fileUploadRepository;

        public AllocationAppService(
            IRepository<Allocation, Guid> repository,
            IRepository<AllocationDetail, Guid> allocationDetailRepository,
            IRepository<FileUpload, Guid> fileUploadRepository)
            : base(repository)
        {
            _allocationRepository = repository;
            _allocationDetailRepository = allocationDetailRepository;
            _fileUploadRepository = fileUploadRepository;
        }
        /// <summary>
        /// 创建调拨单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<AllocationDto> CreateAsync(CreateUpdateAllocationDto input)
        {
            // 1. 生成调拨单号
            input.AllocationNo = await GenerateAllocationNoAsync();

            input.Singer = CurrentUser?.UserName ?? "System";
            var allocation = await base.CreateAsync(input);


            // 3. 创建调拨明细
            if (input.Details != null && input.Details.Any())
            {
                await CreateAllocationDetailsAsync(allocation.Id, input.Details);
            }

            // 4. 保存文件信息
            if (input.Files != null && input.Files.Any())
            {
                // 这里将 input.Files 转换为 FileUploadDto 列表
                var fileDtos = input.Files.Select(f => new FileUploadDto
                {
                    FileName = f.FileName,
                    FileType = f.FileType,
                    FileSize = f.FileSize,
                    FilePath = f.FilePath,
                    BusinessType = f.BusinessType
                }).ToList();

                await CreateFileUploadsAsync(allocation.Id, fileDtos);
            }

            return allocation;
        }
        
        /// <summary>
        /// 修改调拨单
        /// </summary>
        /// <param name="id">调拨单ID</param>
        /// <param name="input">修改信息</param>
        /// <returns></returns>
        public override async Task<AllocationDto> UpdateAsync(Guid id, CreateUpdateAllocationDto input)
        {
            // 1. 查询原始调拨单信息，用于记录日志
            var originalAllocation = await _allocationRepository.GetAsync(id);
            var originalAllocationNo = originalAllocation.AllocationNo;
            
            // 2. 更新调拨单主表信息
            var updatedAllocation = await base.UpdateAsync(id, input);
             

            // 3. 更新调拨明细
            if (input.Details != null && input.Details.Any())
            {
                // 3.1 删除原有明细
                var existingDetails = await _allocationDetailRepository.GetListAsync(d => d.AllocationId == id);
                foreach (var detail in existingDetails)
                {
                    await _allocationDetailRepository.DeleteAsync(detail);
                }
                
                // 3.2 创建新的明细
                await CreateAllocationDetailsAsync(id, input.Details);
            }
            
            // 4. 更新文件信息
            if (input.Files != null)
            {
                // 4.1 获取现有文件列表
                var existingFiles = await _fileUploadRepository.GetListAsync(f => f.BusinessId == id);
                
                // 4.2 删除不在新列表中的文件
                var newFileIds = input.Files.Where(f => f.Id != Guid.Empty).Select(f => f.Id).ToList();
                var filesToDelete = existingFiles.Where(f => !newFileIds.Contains(f.Id)).ToList();
                
                foreach (var file in filesToDelete)
                {
                    await _fileUploadRepository.DeleteAsync(file);
                }
                
                // 4.3 添加新文件
                var newFiles = input.Files.Where(f => f.Id == Guid.Empty).ToList();
                if (newFiles.Any())
                {
                    var fileDtos = newFiles.Select(f => new FileUploadDto
                    {
                        BusinessId=id,
                        FileName = f.FileName,
                        FileType = f.FileType,
                        FileSize = f.FileSize,
                        FilePath = f.FilePath,
                        BusinessType = f.BusinessType
                    }).ToList();
                    
                    await CreateFileUploadsAsync(id, fileDtos);
                }
            }
            
            return updatedAllocation;
        }
        
        private async Task<string> GenerateAllocationNoAsync()
        {
            var date = DateTime.Now.ToString("yyyyMMdd");
            var prefix = $"DB{date}";

            var query = await _allocationRepository.GetQueryableAsync();
            var maxNo = await AsyncExecuter.FirstOrDefaultAsync(
                query.Where(x => x.AllocationNo.StartsWith(prefix))
                     .OrderByDescending(x => x.AllocationNo));

            if (maxNo == null)
            {
                return $"{prefix}0001";
            }

            var currentNumber = int.Parse(maxNo.AllocationNo.Substring(10)) + 1;
            return $"{prefix}{currentNumber:D4}";
        }
        private async Task CreateAllocationDetailsAsync(Guid allocationId, List<CreateUpdateAllocationDetailDto> details)
        {
            foreach (var item in details)
            {
                // 需要手动给 Id 赋值，直接 new AllocationDetail 对象
                var detail = new AllocationDetail
                {
                    AllocationId = allocationId,      // 使用创建的调拨单ID
                    ProductName = item.ProductName,
                    ProductCode = item.ProductCode,
                    Specification = item.Specification,
                    Unit = item.Unit,
                    ProductType = item.ProductType,
                    FromWarehouseStock = item.FromWarehouseStock,
                    ToWarehouseStock = item.ToWarehouseStock,
                    AllocationQuantity = item.AllocationQuantity,
                    UnitPrice = item.UnitPrice,
                    AllocationAmount = item.AllocationQuantity * item.UnitPrice,
                    Remarks = item.Remarks
                };
                await _allocationDetailRepository.InsertAsync(detail);
            }
        }
        private async Task CreateFileUploadsAsync(Guid allocationId, List<FileUploadDto> files)
        {
            foreach (var file in files)
            {
                // 使用构造函数传递参数，需要显式对象初始化器赋值Id
                var fileUpload = new FileUpload(
                    Guid.NewGuid(),           // id
                    file.FileName,            // fileName
                    file.FileType,            // fileType
                    file.FileSize,            // fileSize
                    file.FilePath             // filePath
                )
                {
                    BusinessId = allocationId,
                    BusinessType = file.BusinessType
                };
                await _fileUploadRepository.InsertAsync(fileUpload);
            }
        }
        /// <summary>
        /// 调拨两表联查显示
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<AllocationListDto>> GetAllocationListAsync(PagedAndSortedResultRequestDto input)
        {
            // 1. 构建查询
            var allocations = await _allocationRepository.GetQueryableAsync();
            var details = await _allocationDetailRepository.GetQueryableAsync();
            var records = await _fileUploadRepository.GetQueryableAsync();

            var query = from allocation in allocations
                        join detail in details on allocation.Id equals detail.AllocationId into detailGroup
                        select new AllocationListDto
                        {
                            Id=allocation.Id,
                            AllocationNo = allocation.AllocationNo,
                            Status = allocation.Status,
                            ApplicationDate = allocation.ApplicationDate,
                            AllocationType = allocation.AllocationType,
                            FromWarehouse = allocation.FromWarehouse,
                            ToWarehouse = allocation.ToWarehouse,
                            AllocationQuantity = detailGroup.Sum(d => d.AllocationQuantity),
                            AllocationAmount = detailGroup.Sum(d => d.AllocationAmount),
                            ProductName = detailGroup.Select(d => d.ProductName).FirstOrDefault(),
                            CreationTime = allocation.CreationTime,
                            Handler = allocation.Handler,
                            Singer = allocation.Singer,
                            Remarks = allocation.Remarks,
                            // 文件部分
                            files = records.Where(r => r.BusinessId == allocation.Id)
                                .Select(r => new FileUploadDto
                                {
                                    Id = r.Id,
                                    FileName = r.FileName,
                                    FileSize = r.FileSize,
                                    FilePath = r.FilePath,
                                    UploadTime = r.UploadTime,
                                    BusinessId=r.BusinessId,
                                    BusinessType = r.BusinessType,

                                }).ToList(),
                            AllocationItems= details.Where(x=>x.AllocationId==allocation.Id)
                            .Select(x=>new AllocationDetailDto
                            {
                                Id = x.Id,
                                AllocationId = x.AllocationId,
                                ProductName = x.ProductName,
                                ProductCode = x.ProductCode,
                                Specification = x.Specification,
                                Unit = x.Unit,
                                ProductType = x.ProductType,
                                FromWarehouseStock = x.FromWarehouseStock,
                                ToWarehouseStock = x.ToWarehouseStock,
                                AllocationQuantity = x.AllocationQuantity,
                                UnitPrice = x.UnitPrice,
                                AllocationAmount = x.AllocationAmount,
                                Remarks = x.Remarks
                            }).ToList()

                        };

            // 2. 获取总数
            var totalCount = await AsyncExecuter.CountAsync(query);

            // 3. 排序和分页
            query = query
                .OrderByDescending(x => x.CreationTime)
                .Skip(input.SkipCount)
                .Take(input.MaxResultCount);

            var items = await AsyncExecuter.ToListAsync(query);

            // 4. 返回结果
            return new PagedResultDto<AllocationListDto>(totalCount, items);
        }
    }
}
